#include "Board.h"
#include <QPainter>
#include <QMouseEvent>
#include <QMessageBox>
#include <QDebug> // For debugging output

Board::Board(QWidget *parent) :
    QWidget(parent)
{
    for(int i=0; i<32; ++i)
    {
        _s[i].init(i);
    }
    _selectid = -1;
    _bRedTurn = true;
}

void Board::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int d = 40;
    _r = d/2;
    // 画10横线
    for(int i=1; i<=10; ++i)
    {
        painter.drawLine(QPoint(d, i*d), QPoint(9*d, i*d));
    }
    // 画9竖线
    for(int i=1; i<=9; ++i)
    {
        if(i==1 || i==9)
            painter.drawLine(QPoint(i*d, d), QPoint(i*d, 10*d));
        else
        {
            painter.drawLine(QPoint(i*d, d), QPoint(i*d, 5*d));
            painter.drawLine(QPoint(i*d, 6*d), QPoint(i*d, 10*d));
        }
    }

    // 九宫格
    painter.drawLine(QPoint(4*d, 1*d), QPoint(6*d, 3*d));
    painter.drawLine(QPoint(6*d, 1*d), QPoint(4*d, 3*d));

    painter.drawLine(QPoint(4*d, 8*d), QPoint(6*d, 10*d));
    painter.drawLine(QPoint(6*d, 8*d), QPoint(4*d, 10*d));

    // 绘制32个棋子
    for(int i=0;i <32; ++i)
    {
        drawStone(painter, i);
    }
    /*绘制坐标
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 9; j++) {
            // 在每个交叉点绘制坐标
            painter.drawText(center(i, j), QString("(%1,%2)").arg(i).arg(j));
        }
    }
    */
}

QPoint Board::center(int row, int col)
{
    QPoint ret;
    ret.rx() = (col+1)* _r*2;
    ret.ry() = (row+1)* _r*2;
    return ret;
}

QPoint Board::center(int id)
{
    return center(_s[id]._row, _s[id]._col);
}

void Board::drawStone(QPainter& painter, int id)
{
    if(_s[id]._dead)
        return;

    QPoint c = center(id);
    QRect rect = QRect(c.x()-_r, c.y()-_r, _r*2, _r*2);

    if(id ==_selectid)
        painter.setBrush(QBrush(Qt::gray));
    else
        painter.setBrush(QBrush(Qt::yellow));

    painter.setPen(Qt::black);

    painter.drawEllipse(center(id), _r, _r);

    if(_s[id]._red)
        painter.setPen(Qt::red);
    painter.setFont(QFont("system", _r, 700));

    painter.drawText(rect, _s[id].getText(), QTextOption(Qt::AlignCenter));
}
// 效率不高，应该改进
bool Board::getRowCol(QPoint pt, int &row, int &col)
{
    for(row=0; row<=9; row++)
    {
        for(col=0; col<=8; col++)
        {
            QPoint c = center(row, col);
            int dx = c.x() - pt.x();
            int dy = c.y() - pt.y();
            int dist = dx*dx+dy*dy;
            if(dist < _r*_r)
                return true;
        }
    }
    return false;
}
bool Board::JiangShuaiMove(int moveid, int row, int col, int killid)
{
    /*
        1.首先目标位置在九宫内
        2.移动的步长是一个格子
    */
    if(_s[moveid]._red)
    {
        if(row > 2)return false;
    }
    else
    {
        if(row < 7)return false;
    }

    if(col < 3) return false;
    qDebug()<<killid;
    if(col > 5) return false;

    int dr = _s[moveid]._row - row;
    int dc = _s[moveid]._col - col;
    int d = abs(dr)*10 + abs(dc); // 12, 21   22   10, 1
    if(d == 1 || d == 10)
        return true;

    return false;
}
bool Board::ShiMove(int moveid, int row, int col, int killid)
{
    if(_s[moveid]._red)
    {
        if(row > 2)return false;
    }
    else
    {
        if(row < 7)return false;
    }

    if(col < 3) return false;
    if(col > 5) return false;
    qDebug()<<killid;

    int dr = _s[moveid]._row - row;
    int dc = _s[moveid]._col - col;
    int d = abs(dr)*10 + abs(dc); // 12, 21   22   10, 1
    if(d == 11)
        return true;

    return false;

}
// 判断象/相的移动是否合法
bool Board::XiangMove(int moveid, int row, int col, int killid)
{
    if(_s[moveid]._red)
    {
        if(row > 4) return false; // 红方象不能过河
    }
    else
    {
        if(row < 5) return false; // 黑方相不能过河
    }

    int dr = abs(_s[moveid]._row - row);
    int dc = abs(_s[moveid]._col - col);
    qDebug()<<killid;

    if(dr == 2 && dc == 2) // 象走田字
    {
        // 判断象眼是否被堵
        int eye_row = (_s[moveid]._row + row) / 2;
        int eye_col = (_s[moveid]._col + col) / 2;
        for(int i = 0; i < 32; ++i)
        {
            if(i != moveid && _s[i]._row == eye_row && _s[i]._col == eye_col)
            {
                return false; // 象眼被堵
            }
        }
        return true;
    }

    return false;
}

// 判断车的移动是否合法
bool Board::JuMove(int moveid, int row, int col, int killid)
{
    if(_s[moveid]._row != row && _s[moveid]._col != col)
        return false; // 车只能走直线

    // 判断路径上是否有棋子
    if(_s[moveid]._row == row) // 横向移动
    {
        int start = std::min(_s[moveid]._col, col) + 1;
        int end = std::max(_s[moveid]._col, col);
        for(int c = start; c < end; ++c)
        {
            for(int i = 0; i < 32; ++i)
            {
                if(i != moveid && _s[i]._row == row && _s[i]._col == c)
                {

                    return false; // 路径上有棋子
                }

            }
        }
    }
    else // 纵向移动
    {
        int start = std::min(_s[moveid]._row, row) + 1;
        int end = std::max(_s[moveid]._row, row);
        for(int r = start; r < end; ++r)
        {
            for(int i = 0; i < 32; ++i)
            {
                if(i != moveid && _s[i]._row == r && _s[i]._col == _s[moveid]._col)
                {

                    return false; // 路径上有棋子
                }

            }
        }
    }
    qDebug()<<killid;
    return true;
}

// 判断马的移动是否合法
bool Board::MaMove(int moveid, int row, int col, int killid)
{
    int dr = abs(_s[moveid]._row - row);
    int dc = abs(_s[moveid]._col - col);

    if((dr == 1 && dc == 2) || (dr == 2 && dc == 1)) // 马走日字
    {
        // 判断蹩马腿
        if(dr == 1) // 上下走 1
        {
            int block_row = _s[moveid]._row;
            int block_col = (_s[moveid]._col + col) / 2;
            for(int i = 0; i < 32; ++i)
            {
                if(i != moveid && _s[i]._row == block_row && _s[i]._col == block_col)
                    return false; // 蹩马腿
            }
        }
        else // 左右走 1
        {
            int block_row = (_s[moveid]._row + row) / 2;
            int block_col = _s[moveid]._col;
            for(int i = 0; i < 32; ++i)
            {
                if(i != moveid && _s[i]._row == block_row && _s[i]._col == block_col)
                    return false; // 蹩马腿
            }
        }
        return true;
    }
    qDebug()<<killid;
    return false;
}

// 判断炮的移动是否合法
bool Board::PaoMove(int moveid, int row, int col, int killid)
{
    if(_s[moveid]._row != row && _s[moveid]._col != col)
        return false; // 炮只能走直线

    int barriers = 0; // 障碍物数量

    if(_s[moveid]._row == row) // 横向移动
    {
        int start = std::min(_s[moveid]._col, col) + 1;
        int end = std::max(_s[moveid]._col, col);
        for(int c = start; c < end; ++c)
        {
            for(int i = 0; i < 32; ++i)
            {
                if(i != moveid && _s[i]._row == row && _s[i]._col == c)
                    barriers++;
            }
        }
    }
    else // 纵向移动
    {
        int start = std::min(_s[moveid]._row, row) + 1;
        int end = std::max(_s[moveid]._row, row);
        for(int r = start; r < end; ++r)
        {
            for(int i = 0; i < 32; ++i)
            {
                if(i != moveid && _s[i]._row == r && _s[i]._col == _s[moveid]._col)
                    barriers++;
            }
        }
    }

    if(killid == -1) // 不吃子，路径上不能有子
    {
        return barriers == 0;
    }
    else // 吃子，路径上必须有一个子
    {
        return barriers == 1;
    }
}

// 判断兵/卒的移动是否合法
bool Board::BingMove(int moveid, int row, int col, int killid)
{
    int dr = _s[moveid]._row - row;
    int dc = _s[moveid]._col - col;

    if(_s[moveid]._red) // 红方兵
    {
        if(_s[moveid]._row < 5) // 未过河
        {
            if(dr == -1 && dc == 0) // 只能向前走
                return true;
        }
        else // 已过河
        {
            if((dr == -1 && dc == 0) || (dr == 0 && abs(dc) == 1)) // 可以向前或左右走
                return true;
        }

    }
    else // 黑方卒
    {
        if(_s[moveid]._row > 4) // 未过河
        {
            if(dr == 1 && dc == 0) // 只能向前走
                return true;
        }
        else // 已过河
        {
            if((dr == 1 && dc == 0) || (dr == 0 && abs(dc) == 1)) // 可以向前或左右走
                return true;
        }
    }
    qDebug()<<killid;
    return false;
}

// 将棋盘行列转换为机械臂坐标 (需要根据实际情况调整)
void Board::mapToArmCoords(int row, int col, int &x, int &y, int &z)
{
    // 假设棋盘中心为原点，x轴对应列，y轴对应行，z轴为高度
    // 可以根据实际的机械臂工作空间和棋盘位置进行调整
    int base_x = 100; // 棋盘左上角X坐标
    int base_y = -168;  // 棋盘左上角Y坐标
    int cell_size = 38; // 棋盘格子的尺寸
    int piece_height = 40; // 棋子的高度

    x = base_x + col * cell_size;
    y = base_y + row * cell_size;
    z = piece_height;
}

bool Board::canMove(int moveid, int row, int col, int killid)
{
    if(_s[moveid]._red == _s[killid]._red)//moveid和killid颜色相同)
    {
        //换选择
        _selectid = killid;
        update();
        return false;
    }

    switch(_s[moveid]._type)
    {
    case Stone::JIANG:
        return JiangShuaiMove(moveid, row, col, killid);
        break;
    case Stone::SHI:
        return ShiMove(moveid, row, col, killid);
        break;
    case Stone::XIANG:
        return XiangMove(moveid, row, col, killid);
        break;
    case Stone::CHE:
        if (killid == 4 || killid == 20)   //4 == 红色方将  //黑色方将
        {
            QMessageBox::information(nullptr, QStringLiteral("游戏结束"), QStringLiteral("游戏结束!"));
        }
        return JuMove(moveid, row, col, killid);
        break;
    case Stone::MA:
        if (killid == 4 || killid == 20)   //4 == 红色方将  //黑色方将
        {
            QMessageBox::information(nullptr, QStringLiteral("游戏结束"), QStringLiteral("游戏结束!"));
        }
        return MaMove(moveid, row, col, killid);
        break;
    case Stone::PAO:
        if (killid == 4 || killid == 20)   //4 == 红色方将  //黑色方将
        {
            QMessageBox::information(nullptr, QStringLiteral("游戏结束"), QStringLiteral("游戏结束!"));
        }
        return PaoMove(moveid, row, col, killid);
        break;
    case Stone::BING:
        if (killid == 4 || killid == 20)   //4 == 红色方将  //黑色方将
        {
            QMessageBox::information(nullptr, QStringLiteral("游戏结束"), QStringLiteral("游戏结束!"));
        }
        return BingMove(moveid, row, col, killid);
        break;
    }

    return true;
}

void Board::mouseReleaseEvent(QMouseEvent *ev)
{
    QPoint pt = ev->pos();
    // 将pt转化成象棋的行列值
    // 判断这个行列值上面有没有棋子
    int row, col;
    bool bRet = getRowCol(pt, row, col);
    if(bRet == false) // 点到棋盘外
        return;

    int i;
    int clickid = -1;
    for(i=0;i<32;++i)
    {
        if(_s[i]._row == row && _s[i]._col == col && _s[i]._dead== false)
        {
            break;
        }
    }

    if(i<32)
    {
        clickid = i;

    }

    if(_selectid == -1)
    {
        if(clickid != -1)
        {
            if(_bRedTurn == _s[clickid]._red)
            {
                _selectid = clickid;
                update();
            }
        }
    }
    else
    {
        if(canMove(_selectid, row, col, clickid))
        {


            // 获取移动前的坐标
            int old_row = _s[_selectid]._row;
            int old_col = _s[_selectid]._col;

            // 调用机械臂抓取函数
            int get_x, get_y, get_z;
            mapToArmCoords(old_row, old_col, get_x, get_y, get_z);
            w.actionGroupGet(get_y, get_x, get_z,1000); // 假设抓取时间为 2
            qDebug()<< "get_x:" <<"get_y:" <<"get_z:" << get_x <<get_y <<get_z;
            /*走棋*/
            _s[_selectid]._row = row;
            _s[_selectid]._col = col;

            QTimer::singleShot(3*1000, this, [this,row,col]() {
                // 调用机械臂放置函数
                int put_x, put_y, put_z;
                mapToArmCoords(row, col, put_x, put_y, put_z);
                w.actionGroupPut(put_y, put_x, put_z, 1000); // 假设放置时间为 2
                qDebug()<< "put_x:" <<"put_y:" <<"put_z:" << put_x <<put_y <<put_z;
            });


            if(clickid != -1)
            {
                _s[clickid]._dead = true;
            }
            _selectid = -1;
            _bRedTurn = !_bRedTurn;
            update();
        }
    }
}
